home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 1 / Gold Medal Software Volume 1 (Gold Medal) (1994).iso / prog / cextract.arj / CEXTRACT.TAR / cextract / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-08  |  52.8 KB  |  2,230 lines

  1. /*
  2.  *
  3.  * cextract input/output routines.
  4.  *
  5.  * Copyright (c) 1992 by Adam Bryant
  6.  *
  7.  * See the Copyright notice in the file parse.c or in the manual page.
  8.  *
  9.  */
  10. #include "xtract.h"
  11. #ifndef VAXC
  12. #include <pwd.h>
  13. #ifdef cyber
  14. extern struct passwd *getpwuid();
  15. #endif /* cyber */
  16. #ifdef CLIX
  17. extern struct passwd *getpwuid();
  18. #endif /* CLIX */
  19. #endif /* VAXC */
  20.  
  21. /* declarations */
  22. char cur_cfg_file[FNAME_SIZE], header_string[MID_SIZE];
  23. int out_filenum = 0;
  24.  
  25. /* storage for the temporary buffers */
  26. P_BUFDATA tempbuf[2] = { NULL, NULL };
  27. #ifdef SETBUFFER
  28. char outbuffer[BUFFER_SIZE], inbuffer[BUFFER_SIZE];
  29. #endif /* SETBUFFER */
  30.  
  31. /* output file */
  32. FILE *fpout;
  33. char output_file[2][MID_SIZE];
  34.  
  35. /* preprocessor */
  36. char cpp_prog[MID_SIZE];
  37.  
  38. #ifdef NO_STRSTR
  39. /*
  40.  * This function was written to handle Xenix sites without strstr().
  41.  * [It is a straightforward function, which I cannot take credit for,
  42.  * which was given by an anonymous c.s.r reviewer.]
  43.  */
  44. char *
  45. strstr(hoststr, search)
  46.   char *hoststr;
  47.   char *search;
  48. {
  49.   int len1 = 0, len2 = 0, index = 0;
  50.   char *ptr1, *ptr2, *loc_ptr;
  51.  
  52.   len1 = strlen(hoststr);
  53.   len2 = strlen(search);
  54.   while ( len1 >= len2 ) {
  55.     index = len2;
  56.     loc_ptr = hoststr;
  57.     ptr1 = hoststr;
  58.     ptr2 = search;
  59.     while ( (index > 0) && (loc_ptr != NULL) ) {
  60.       if ( (*ptr1) == (*ptr2) ) {
  61.     ++ptr1;
  62.     ++ptr2;
  63.     --index;
  64.       } else {
  65.     loc_ptr = NULL;
  66.       }
  67.     }
  68.     if ( loc_ptr != NULL ) {
  69.       return( loc_ptr );
  70.     } else {
  71.       ++hoststr;
  72.       --len1;
  73.     }
  74.   }
  75.   return( NULL );
  76. }
  77. #endif /* NO_STRSTR */
  78.  
  79. /* indicate if on or off */
  80. static void
  81. quick_rc (str, mode, fp)
  82.   char *str;
  83.   int mode;
  84.   FILE *fp;
  85. {
  86.   sprintf(tmp_str, "%s%s\n", mode ? "":"!", str);
  87.   fput_string(tmp_str, fp);
  88. }
  89.  
  90. /* check for divergent options */
  91. static void
  92. opt_quickrc (which, str, fp)
  93.   Optype which;
  94.   char *str;
  95.   FILE *fp;
  96. {
  97. #ifdef CHECK_INPUTS
  98.   if ((which < 0) ||
  99.       (which >= OPT_NUMBER)) {
  100.     fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  101.         which);
  102.     exit(1);
  103.   }
  104. #endif /* CHECK_INPUTS */
  105.   if (global_opts[0][which] != global_opts[1][which]) {
  106.     fput_string("extract-only ", fp);
  107.     quick_rc(str, global_opts[0][which], fp);
  108.     fput_string("doc-only ", fp);
  109.   }
  110.   quick_rc(str, global_opts[1][which], fp);
  111. }
  112.  
  113. /* check for divergent numeric options */
  114. static void
  115. opt_numericrc (which, str, fp)
  116.   Optype which;
  117.   char *str;
  118.   FILE *fp;
  119. {
  120. #ifdef CHECK_INPUTS
  121.   if ((which < 0) ||
  122.       (which >= OPT_NUMBER)) {
  123.     fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  124.         which);
  125.     exit(1);
  126.   }
  127. #endif /* CHECK_INPUTS */
  128.   if (global_opts[0][which] != global_opts[1][which]) {
  129.     fput_string("extract-only ", fp);
  130.     sprintf(tmp_str, "%s: %d\n", str, global_opts[0][which]);
  131.     fput_string(tmp_str, fp);
  132.     fput_string("doc-only ", fp);
  133.   }
  134.   sprintf(tmp_str, "%s: %d\n", str, global_opts[1][which]);
  135.   fput_string(tmp_str, fp);
  136. }
  137.  
  138. /* choose between three modes of the given option */
  139. static void
  140. opt_triplerc (which, str0, str1, str2, fp)
  141.   Optype which;
  142.   char *str0, *str1, *str2;
  143.   FILE *fp;
  144. {
  145. #ifdef CHECK_INPUTS
  146.   if ((which < 0) ||
  147.       (which >= OPT_NUMBER)) {
  148.     fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
  149.         which);
  150.     exit(1);
  151.   }
  152. #endif /* CHECK_INPUTS */
  153.   if (global_opts[0][which] != global_opts[1][which]) {
  154.  
  155.     /* first on */
  156.     fput_string("extract-only ", fp);
  157.     switch (global_opts[0][which]) {
  158.     case 1:
  159.       fput_string(str1, fp);
  160.       break;
  161.     case 2:
  162.       fput_string(str2, fp);
  163.       break;
  164.     default:
  165.       fput_string(str0, fp);
  166.       break;
  167.     }
  168.     fput_string("\ndoc-only ", fp);
  169.  
  170.   }
  171.  
  172.   /* second on */
  173.   switch (global_opts[1][which]) {
  174.   case 1:
  175.     fput_string(str1, fp);
  176.     break;
  177.   case 2:
  178.     fput_string(str2, fp);
  179.     break;
  180.   default:
  181.     fput_string(str0, fp);
  182.     break;
  183.   }
  184.   fput_string("\n", fp);
  185. }
  186.  
  187. /* display string appropriately */
  188. static void
  189. opt_stringrc (ind, str, fp)
  190.   int ind;
  191.   char *str;
  192.   FILE *fp;
  193. {
  194.   if (ind != 2) {
  195.     if (ind == 1) {
  196.       fput_string("doc-only ", fp);
  197.     } else {
  198.       fput_string("extract-only ", fp);
  199.     }
  200.   }
  201.   fput_string(str, fp);
  202. }
  203.  
  204. /* attempt build of system config file */
  205. static void
  206. build_rc (fname)
  207.   char *fname;
  208. {
  209.   int undlen = strlen(UNDEF_LEADER);
  210.   int deflen = strlen(DEF_LEADER);
  211.   int inclen = strlen(INC_LEADER);
  212.   P_MACRO macro_temp;
  213.   P_SUBST sub_tmp;
  214.   FILE *rc_fp;
  215.   int len;
  216.  
  217.   /* open and write to config file */
  218.   if ((rc_fp = fopen(fname, "w")) == NULL) {
  219.     err_msg("unable to open system configuration file for writing");
  220.     exit(1);
  221.   }
  222.  
  223.   /* provide header */
  224.   sprintf(tmp_str, "#\n# File: %s\n#\n", fname);
  225.   fput_string(tmp_str, rc_fp);
  226.   fput_string("#   This config file was generated by ", rc_fp);
  227.   sprintf(tmp_str, "version %d.%d of %s.\n",
  228.       VERSION, PATCHLEVEL, prog_name);
  229.   fput_string(tmp_str, rc_fp);
  230.   fput_string("#   Edit carefully.\n", rc_fp);
  231.   fput_string("#\n#   Created: ", rc_fp);
  232.   strcpy(tmp_str, mach_time());
  233.   len = strlen(tmp_str);
  234.   if ((len > 0) && (tmp_str[len - 1] == '\n')) {
  235.     tmp_str[len - 1] = '\0';
  236.   }
  237.   fput_string(tmp_str, rc_fp);
  238.   fput_string("\n#\n", rc_fp);
  239.  
  240.   /* first varargs */
  241.   if (vargs_find()) {
  242.     fprintf(stderr,
  243.         "The generation of the varargs and FILE replacements might have\n");
  244.     fprintf(stderr,
  245.         "failed.  You may want to manually enter the necessary \"replace\"\n");
  246.     fprintf(stderr,
  247.         "commands into the system configuration file.\n");
  248.   }
  249.  
  250.   /* begin with the CPP */
  251.   if (cpp_prog[0] != '\0') {
  252.     sprintf(tmp_str, "cpp-program: %s\n", cpp_prog);
  253.     fput_string(tmp_str, rc_fp);
  254.   }
  255.  
  256.   /* handle output file */
  257.   if (strcmp(output_file[0], output_file[1]) != 0) {
  258.     if (output_file[0][0] != '\0') {
  259.       fput_string("extract-only ", rc_fp);
  260.       sprintf(tmp_str, "output-file: %s\n", output_file[0]);
  261.       fput_string(tmp_str, rc_fp);
  262.     }
  263.     if (output_file[1][0] != '\0') {
  264.       fput_string("doc-only ", rc_fp);
  265.     }
  266.   }
  267.   if (output_file[1][0] != '\0') {
  268.     sprintf(tmp_str, "output-file: %s\n", output_file[1]);
  269.     fput_string(tmp_str, rc_fp);
  270.   }
  271.  
  272.   /* differentiate modes */
  273. #ifdef NOT_DONE
  274.   switch (doc_extract) {
  275.   case DOC_NONE:
  276.     fput_string("extract-mode\n", rc_fp);
  277.     break;
  278.   case DOC_NORMAL:
  279.     fput_string("doc-mode\n", rc_fp);
  280.     break;
  281.   case DOC_ROFF:
  282.     fput_string("troff-mode\n", rc_fp);
  283.     break;
  284.   default:
  285.     fprintf(stderr, "\tError, unknown mode.\n\n");
  286.     exit(1);
  287.     break;
  288.   }
  289. #else
  290.   if (doc_extract == DOC_ROFF) {
  291.     fput_string("doc-only troff-mode\n", rc_fp);
  292.   }
  293. #endif /* NOT_DONE */
  294.  
  295.   /* output all options */
  296.   if (header_string[0] != '\0') {
  297.     sprintf(tmp_str, "header-string: %s\n", header_string);
  298.     fput_string(tmp_str, rc_fp);
  299.   }
  300.   opt_quickrc(OPT_COMPACT, "merge-output", rc_fp);
  301.   opt_quickrc(OPT_BOTHUSE, "dual-output", rc_fp);
  302.   opt_quickrc(OPT_STDCUSE, "ansi-code", rc_fp);
  303.   opt_quickrc(OPT_SHOWANYWAY, "show-anyway", rc_fp);
  304.   opt_triplerc(OPT_SORTMODE, "!sort", "sort-by-files", "sort-all", rc_fp);
  305.   opt_numericrc(OPT_WRAPPOINT, "wrap-parameters", rc_fp);
  306.   opt_numericrc(OPT_TABWIDTH, "tab-width", rc_fp);
  307.   opt_quickrc(OPT_TYPEWRAP, "break-after-types", rc_fp);
  308.   opt_quickrc(OPT_FIRSTCOMMENT, "first-comments", rc_fp);
  309.   opt_quickrc(OPT_PREPEND, "prepend-filename", rc_fp);
  310.   opt_quickrc(OPT_COMMENTS, "yank-comments", rc_fp);
  311.   opt_triplerc(OPT_STATICMODE, "statics: none", "statics: only",
  312.            "statics: any", rc_fp);
  313.   opt_quickrc(OPT_EXTERNS, "externs", rc_fp);
  314.   opt_quickrc(OPT_SINGLECOMMENTS, "single-comments", rc_fp);
  315.  
  316.   /* show all macros */
  317.   if (macro_list != NULL) {
  318.  
  319.     for (macro_temp = macro_list;
  320.      macro_temp != NULL;
  321.      macro_temp = macro_temp->next) {
  322.       if (strncmp(DEF_LEADER, macro_temp->m_str, deflen) == 0) {
  323.     sprintf(tmp_str, "define: %s\n",
  324.         macro_temp->m_str + deflen);
  325.       } else if (strncmp(INC_LEADER, macro_temp->m_str, inclen) == 0) {
  326.     sprintf(tmp_str, "include: %s\n",
  327.         macro_temp->m_str + inclen);
  328.       } else if (strncmp(UNDEF_LEADER, macro_temp->m_str, undlen) == 0) {
  329.     sprintf(tmp_str, "undefine: %s\n",
  330.         macro_temp->m_str + deflen);
  331.       } else {
  332.     fprintf(stderr, "unknown macro encountered: %s\n",
  333.         macro_temp->m_str);
  334.     continue;
  335.       }
  336.       opt_stringrc(macro_temp->usewhen, tmp_str, rc_fp);
  337.     
  338.     }
  339.   }
  340.  
  341.   /* check substitutions */
  342.   if (subst_list != NULL) {
  343.  
  344.     for (sub_tmp = subst_list;
  345.      sub_tmp != NULL;
  346.      sub_tmp = sub_tmp->next) {
  347.  
  348.       /* check it */
  349.       switch (sub_tmp->submode) {
  350.       case SUBST_FULL:
  351.     /* the full string needs replacing? */
  352.     sprintf(tmp_str, "replace all \"%s\" with \"%s\"\n",
  353.         sub_tmp->from_str, sub_tmp->to_str);
  354.     break;
  355.       case SUBST_TYPE:
  356.     /* the type only needs replacing? */
  357.     sprintf(tmp_str, "replace type \"%s\" with \"%s\"\n",
  358.         sub_tmp->from_str, sub_tmp->to_str);
  359.     break;
  360.       case SUBST_NAME:
  361.     /* the variable only needs replacing? WHY!? */
  362.     sprintf(tmp_str, "replace name \"%s\" with \"%s\"\n",
  363.         sub_tmp->from_str, sub_tmp->to_str);
  364.     break;
  365.       }
  366.       opt_stringrc(sub_tmp->usewhen, tmp_str, rc_fp);
  367.  
  368.     }
  369.   }
  370.  
  371.   /* done */
  372.   fput_string("#\n", rc_fp);
  373.   fclose(rc_fp);
  374. }
  375.  
  376. /* close up properly; sending out final output */
  377. void
  378. cxt_close()
  379. {
  380.   P_BUFDATA holdbuf;
  381.   int len;
  382.  
  383.   /* close up buffers and open file */
  384.   out_char(-1, '\0');
  385.   if (output_file[doc_extract != DOC_NONE][0] != '\0') {
  386.     if ((fpout = fopen(output_file[doc_extract != DOC_NONE], "w")) == NULL) {
  387.       sprintf(tmp_str, "unable to open output file <%s>",
  388.           output_file[doc_extract != DOC_NONE]);
  389.       err_msg(tmp_str);
  390.       exit(1);
  391.     }
  392.   }
  393.  
  394. #ifdef SETBUFFER
  395.   /* now set the buffer */
  396.   setbuffer(fpout, outbuffer, BUFFER_SIZE);
  397. #endif /* SETBUFFER */
  398.  
  399.   /* send everything straight out in doc modes */
  400.   if (doc_extract != DOC_NONE) {
  401.  
  402.     /* do all */
  403.     for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
  404.       /* output and free */
  405.       holdbuf = tempbuf[1]->next;
  406.       fput_string(tempbuf[1]->data, fpout);
  407.       free(tempbuf[1]);
  408.     }
  409.  
  410.     /* close up */
  411.     if (fpout != stdout) {
  412.       if (fclose(fpout) == EOF) {
  413.     err_msg("Error in closing output file");
  414.     exit(1);
  415.       }
  416.     }
  417.     return;
  418.   }
  419.  
  420.   /* start header */
  421.   fput_string("/*\n *   This file was automatically generated by ", fpout);
  422.   sprintf(tmp_str, "version %d.%d of %s.\n",
  423.       VERSION, PATCHLEVEL, prog_name);
  424.   fput_string(tmp_str, fpout);
  425.   fput_string(" *   Manual editing not recommended.\n", fpout);
  426.   fput_string(" *\n *   Created: ", fpout);
  427.   strcpy(tmp_str, mach_time());
  428.   len = strlen(tmp_str);
  429.   if ((len > 0) && (tmp_str[len - 1] == '\n')) {
  430.     tmp_str[len - 1] = '\0';
  431.   }
  432.   fput_string(tmp_str, fpout);
  433.   fput_string("\n */\n", fpout);
  434.  
  435.   /* enclosing directives */
  436.   if (header_string[0] != '\0') {
  437.     sprintf(tmp_str, "#ifndef %s\n", header_string);
  438.     fput_string(tmp_str, fpout);
  439.   } else {
  440.     fput_string("#ifndef __CEXTRACT__\n", fpout);
  441.   }
  442.   if (header_string[0] != '\0') {
  443.     sprintf(tmp_str, "#define %s\n", header_string);
  444.     fput_string(tmp_str, fpout);
  445.   }
  446.   if (get_option(OPT_COMPACT)) {
  447.     fput_string("#if __STDC__\n", fpout);
  448.     fput_string("#define PL_(x) x\n", fpout);
  449.     fput_string("#else\n", fpout);
  450.     fput_string("#define PL_(x) ( )\n", fpout);
  451.     fput_string("#endif /* __STDC__ */\n", fpout);
  452.   } else if (get_option(OPT_BOTHUSE) ||
  453.          get_option(OPT_STDCUSE)) {
  454.     fput_string("#if __STDC__\n", fpout);
  455.   }
  456.  
  457.   /* first region */
  458.   for (; tempbuf[0] != NULL; tempbuf[0] = holdbuf) {
  459.     /* output and free */
  460.     holdbuf = tempbuf[0]->next;
  461.     fput_string(tempbuf[0]->data, fpout);
  462.     free(tempbuf[0]);
  463.   }
  464.  
  465.   /* more? */
  466.   if (!get_option(OPT_COMPACT) &&
  467.       get_option(OPT_BOTHUSE)) {
  468.  
  469.     /* separator */
  470.     fput_string("\n#else /* __STDC__ */\n", fpout);
  471.  
  472.     /* send second portion */
  473.     for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
  474.       /* output and free */
  475.       holdbuf = tempbuf[1]->next;
  476.       fput_string(tempbuf[1]->data, fpout);
  477.       free(tempbuf[1]);
  478.     }
  479.  
  480.   }
  481.  
  482.   /* finish header */
  483.   putc('\n', fpout);
  484.   if (get_option(OPT_COMPACT)) {
  485.     fput_string("#undef PL_\n", fpout);
  486.   } else if (get_option(OPT_BOTHUSE) ||
  487.          get_option(OPT_STDCUSE)) {
  488.     fput_string("#endif /* __STDC__ */\n", fpout);
  489.   }
  490.   if (header_string[0] != '\0') {
  491.     sprintf(tmp_str, "#endif /* %s */\n", header_string);
  492.     fput_string(tmp_str, fpout);
  493.   } else {
  494.     fput_string("#endif /* __CEXTRACT__ */\n", fpout);
  495.   }
  496.  
  497.   /* close up */
  498.   if (fpout != stdout) {
  499.     if (fclose(fpout) == EOF) {
  500.       err_msg("Error in closing output file");
  501.       exit(1);
  502.     }
  503.   }
  504. }
  505.  
  506. /* output results of entire file search */
  507. void
  508. send_file()
  509. {
  510.   /* sort? */
  511.   if (get_option(OPT_SORTMODE) != SORT_NONE) {
  512.     sort_proto();
  513.   }
  514.  
  515.   /* output everything */
  516.   while (proto_list != NULL) {
  517.  
  518.     /* determine type */
  519.     if (doc_extract == DOC_NONE) {
  520.  
  521.       /* ANSI? */
  522.       if (get_option(OPT_COMPACT)) {
  523.     out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  524.       } else if (get_option(OPT_BOTHUSE)) {
  525.     out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  526.     out_proto(1, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
  527.           get_option(OPT_SHOWANYWAY) *
  528.           get_option(OPT_COMMENTS));
  529.       } else {
  530.     if (get_option(OPT_STDCUSE)) {
  531.       out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  532.     } else {
  533.       out_proto(0, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
  534.             get_option(OPT_COMMENTS));
  535.     }
  536.       }
  537.  
  538.     } else {
  539.  
  540.       /* ANSI in docs */
  541.       out_proto(1, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
  542.  
  543.     }
  544.     total_out++;
  545.     pop_proto();
  546.  
  547.   }
  548. }
  549.  
  550. /* does the string match a minimum number of characters */
  551. int
  552. minmatch_str(str_in, str_base, num)
  553.   char *str_in, *str_base;
  554.   int num;
  555. {
  556.   int i;
  557.  
  558.   for (i = 0; (str_base[i] != '\0') && (str_in[i] != '\0') &&
  559.        (str_in[i] != ':') && (str_in[i] != '='); i++) {
  560.     if (str_base[i] != str_in[i]) return(0);
  561.   }
  562.   if (i >= num) {
  563.     return(i);
  564.   }
  565.   return(0);
  566. }
  567.  
  568. /* send an error message about a config command */
  569. static void
  570. cfg_err(str, cmd_line)
  571.   char *str;
  572.   int cmd_line;
  573. {
  574.   fprintf(stderr, "%s", str);
  575.   if (cmd_line) {
  576.     fprintf(stderr, " on the command line\n");
  577.   } else if (cur_cfg_file[0] == '\0') {
  578.     fprintf(stderr, " in a configuration file\n");
  579.   } else {
  580.     fprintf(stderr, " in %s\n", cur_cfg_file);
  581.   }
  582. }
  583.  
  584. /* mode selector */
  585. static int setmode_value;
  586.  
  587. #ifndef VMS
  588. /* parse string for single char commands */
  589. static void
  590. singlechar_cmds(cmd_str, set_val)
  591.   char *cmd_str;
  592.   int set_val;
  593. {
  594.   int count, len = strlen(cmd_str);
  595.  
  596.   for (count = 0; count < len; count++) {
  597.  
  598.     switch (cmd_str[count]) {
  599.     case 'A':
  600.       if (files_parsed == 0) {
  601.     if (set_val) {
  602.       set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
  603.     } else {
  604.       set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  605.     }
  606.       } else {
  607.     fprintf(stderr, "The '-A' flag must precede any file arguments\n");
  608.     show_usage();
  609.       }
  610.       break;
  611.     case 'a':
  612.       if (get_option(OPT_SORTMODE) != SORT_ALL) {
  613.     if (set_val) {
  614.       set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
  615.     } else {
  616.       set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  617.     }
  618.       }
  619.       break;
  620.     case 'b':
  621.       build_rc(CONFIG_FILE);
  622.       exit(0);
  623.       break;
  624.     case 'B':
  625.       build_rc(SYS_CONFIG);
  626.       exit(0);
  627.     case 'C':
  628.       set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
  629.       break;
  630.     case 'c':
  631.       set_option(OPT_COMMENTS, setmode_value, set_val);
  632.       break;
  633.     case 'D':
  634.     case 'd':
  635.       /* add to macro list */
  636.       if (count != 0) {
  637.     fprintf(stderr, "The -D flag must be a separate argument\n");
  638.     show_usage();
  639.       }
  640.       sprintf(tmp_str, "%s%s", DEF_LEADER, cmd_str + 1);
  641.       add_macro(setmode_value, tmp_str);
  642.       return;
  643.     case 'E':
  644.       set_option(OPT_EXTERNS, setmode_value, set_val);
  645.       break;
  646.     case 'F':
  647.       set_option(OPT_PREPEND, setmode_value, set_val);
  648.       break;
  649.     case 'f':
  650.       /* set font */
  651.       if (count != 0) {
  652.     fprintf(stderr, "The -f flag must be a separate argument\n");
  653.     show_usage();
  654.       } else if (files_parsed > 0) {
  655.     fprintf(stderr, "The -f flag must precede any file arguments\n");
  656.     show_usage();
  657.       }
  658.  
  659.       /* check format */
  660.       if ((strlen(cmd_str + 1) < 2) ||
  661.       (strlen(cmd_str + 1) > 3)) {
  662.     fprintf(stderr, "A proper troff font must be specified\n");
  663.     show_usage();
  664.       }
  665.  
  666.       /* check font */
  667.       switch (cmd_str[1]) {
  668.       case '1':
  669.       case 't':
  670.       case 'T':
  671.     /* title */
  672.     strncpy(ft_title, &(cmd_str[2]), 2);
  673.     ft_title[2] = '\0';
  674.     break;
  675.       case '2':
  676.       case 'c':
  677.       case 'C':
  678.     /* comment */
  679.     strncpy(ft_comment, &(cmd_str[2]), 2);
  680.     ft_comment[2] = '\0';
  681.     break;
  682.       case '3':
  683.       case 'n':
  684.       case 'N':
  685.     /* function name */
  686.     strncpy(ft_name, &(cmd_str[2]), 2);
  687.     ft_name[2] = '\0';
  688.     break;
  689.       case '4':
  690.       case 'p':
  691.       case 'P':
  692.     /* prototype list */
  693.     strncpy(ft_plist, &(cmd_str[2]), 2);
  694.     ft_plist[2] = '\0';
  695.     break;
  696.       default:
  697.     /* huh? */
  698.     fprintf(stderr, "unknown font selector '%c' in %s\n",
  699.         cmd_str[1], cmd_str);
  700.     show_usage();
  701.       }
  702.       return;
  703.     case 'H':
  704.       /* header string */
  705.       if (files_parsed == 0) {
  706.     if (count != 0) {
  707.       fprintf(stderr, "The -H flag must be a separate argument\n");
  708.       show_usage();
  709.     }
  710.     if (cmd_str[2] != '\0') {
  711.       strcpy(header_string, cmd_str + 1);
  712.     } else {
  713.       fprintf(stderr,
  714.           "A string must be specified following the -H flag\n");
  715.       show_usage();
  716.     }
  717.       } else {
  718.     fprintf(stderr, "The -H flag must precede any file arguments\n");
  719.     show_usage();
  720.       }
  721.       return;
  722.     case 'I':
  723.     case 'i':
  724.       /* include file */
  725.       if (count != 0) {
  726.     fprintf(stderr, "The -I flag must be a separate argument\n");
  727.     show_usage();
  728.       }
  729.       sprintf(tmp_str, "%s%s", INC_LEADER, cmd_str + 1);
  730.       add_macro(setmode_value, tmp_str);
  731.       return;
  732.     case 'm':
  733.       set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
  734.       break;
  735.     case 'N':
  736.       /* roff mode */
  737.       if (files_parsed > 0) {
  738.     fprintf(stderr, "The -N flag must precede any file arguments\n");
  739.     show_usage();
  740.       }
  741.       doc_extract = DOC_ROFF;
  742.       break;
  743.     case 'n':
  744.       /* docs mode */
  745.       if (files_parsed > 0) {
  746.     fprintf(stderr, "The -n flag must precede any file arguments\n");
  747.     show_usage();
  748.       }
  749.       doc_extract = DOC_NORMAL;
  750.       break;
  751.     case 'o':
  752.       if (out_filenum < 3) {
  753.     out_filenum = 1;
  754.       } else {
  755.     fprintf(stderr, "The -o flag must precede any file arguments\n");
  756.     show_usage();
  757.       }
  758.       break;
  759.     case 'p':
  760.       /* ANSI C prototypes */
  761.       if (files_parsed == 0) {
  762.     set_option(OPT_STDCUSE, setmode_value, set_val);
  763.       } else {
  764.     fprintf(stderr, "The -p flag must precede any file arguments\n");
  765.     show_usage();
  766.       }
  767.       break;
  768.     case 'P':
  769.       /* both ANSI and K&R */
  770.       if (files_parsed == 0) {
  771.     set_option(OPT_BOTHUSE, setmode_value, set_val);
  772.       } else {
  773.     fprintf(stderr, "The -P flag must precede any file arguments\n");
  774.     show_usage();
  775.       }
  776.       break;
  777.     case 'Q':
  778.       /* not here */
  779.       fprintf(stderr, "The -Q flag must be the very first argument\n");
  780.       show_usage();
  781.     case 'q':
  782.       /* input config file */
  783.       if (count != 0) {
  784.     fprintf(stderr, "The -q flag must be a separate argument\n");
  785.     show_usage();
  786.       }
  787.       if (cmd_str[1] != '\0') {
  788.     parse_config(cmd_str + 1);
  789.       } else {
  790.     fprintf(stderr, "No file was specified for the -q argument\n");
  791.     show_usage();
  792.       }
  793.       return;
  794.     case 'r':
  795.       /* remove variable names */
  796.       set_option(OPT_NONAMES, setmode_value, set_val);
  797.       break;
  798.     case 'S':
  799.       /* full info for non-ANSI */
  800.       set_option(OPT_SHOWANYWAY, setmode_value, set_val);
  801.       break;
  802.     case 's':
  803.       /* static functions */
  804.       if ((cmd_str[count + 1] == ':') ||
  805.       (cmd_str[count + 1] == '=')) {
  806.     count += 2;
  807.     switch(cmd_str[count]) {
  808.     case 'a':
  809.       /* all */
  810.       set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  811.       if ((strncmp(cmd_str + count, "all", 3) == 0) ||
  812.           (strncmp(cmd_str + count, "any", 3) == 0)) {
  813.         count += 3;
  814.       } else {
  815.         count++;
  816.       }
  817.       break;
  818.     case 'o':
  819.       /* only statics */
  820.       set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
  821.       if (strncmp(cmd_str + count, "only", 4) == 0) {
  822.         count += 4;
  823.       } else {
  824.         count++;
  825.       }
  826.       break;
  827.     case 'n':
  828.       /* no statics */
  829.       set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  830.       if (strncmp(cmd_str + count, "none", 4) == 0) {
  831.         count += 4;
  832.       } else if (strncmp(cmd_str + count, "no", 2) == 0) {
  833.         count += 2;
  834.       } else {
  835.         count++;
  836.       }
  837.       break;
  838.     default:
  839.       /* huh? */
  840.       count--;
  841.       break;
  842.     }
  843.       } else {
  844.     if (set_val) {
  845.       set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  846.     } else {
  847.       set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  848.     }
  849.       }
  850.       break;
  851.     case 'T':
  852.       /* tab width */
  853.       if (count != 0) {
  854.     fprintf(stderr, "The -T flag must be a separate argument\n");
  855.     show_usage();
  856.       }
  857.       if (len == 2) {
  858.     set_option(OPT_TABWIDTH, setmode_value, 8);
  859.       } else {
  860.     int tab_width = 0;
  861.     for (count++; count < len; count++) {
  862.       if (!isdigit(cmd_str[count])) {
  863.         fprintf(stderr, "Unknown tab width in argument %s\n",
  864.             cmd_str);
  865.         show_usage();
  866.       } else {
  867.         tab_width *= 10;
  868.         tab_width += cmd_str[count] - '0';
  869.       }
  870.     }
  871.     set_option(OPT_TABWIDTH, setmode_value, tab_width);
  872.       }
  873.       return;
  874.     case 'U':
  875.     case 'u':
  876.       /* undefine */
  877.       if (count != 0) {
  878.     fprintf(stderr, "The -U flag must be a separate argument\n");
  879.     show_usage();
  880.       }
  881.       if (removed_macro(setmode_value, cmd_str + 1) != TRUE) {
  882.     sprintf(tmp_str, "%s%s", UNDEF_LEADER, cmd_str + 1);
  883.     add_macro(setmode_value, tmp_str);
  884.       }
  885.       return;
  886.     case 'V':
  887.       show_settings();
  888.     case 'v':
  889.       show_version();
  890.       exit(0);
  891.     case 'W':
  892.       /* wrapping */
  893.       set_option(OPT_TYPEWRAP, setmode_value, set_val);
  894.       break;
  895.     case 'w':
  896.       /* more wrapping */
  897.       if (isdigit(cmd_str[count + 1])) {
  898.  
  899.     /* use given wrap locale */
  900.     int wrap_point = 0;
  901.     for (count++; isdigit(cmd_str[count]); count++) {
  902.       wrap_point *= 10;
  903.       wrap_point += (cmd_str[count] - '0');
  904.     }
  905.     count--;
  906.     set_option(OPT_WRAPPOINT, setmode_value, wrap_point);    
  907.  
  908.       } else {
  909.  
  910.     if (set_val) {
  911.       /* default */
  912.       set_option(OPT_WRAPPOINT, setmode_value, 72);
  913.     } else {
  914.       /* off */
  915.       set_option(OPT_WRAPPOINT, setmode_value, 0);
  916.     }
  917.  
  918.       }
  919.       break;
  920.     case 'x':
  921.       /* extraction mode */
  922.       if (files_parsed > 0) {
  923.     fprintf(stderr, "The -x flag must precede any file arguments\n");
  924.     show_usage();
  925.       }
  926.       doc_extract = DOC_NONE;
  927.       break;
  928.     case 'Y':
  929.       /* C preprocessor */
  930.       if (files_parsed == 0) {
  931.     if (count != 0) {
  932.       fprintf(stderr, "The -Y flag must be a separate argument\n");
  933.       show_usage();
  934.     }
  935.     if (cmd_str[2] != '\0') {
  936.       strcpy(cpp_prog, cmd_str + 1);
  937.     } else {
  938.       fprintf(stderr,
  939.           "A string must be specified following the -Y flag\n");
  940.       show_usage();
  941.     }
  942.       } else {
  943.     fprintf(stderr, "The -Y flag must precede any file arguments\n");
  944.     show_usage();
  945.       }
  946.       break;
  947.     case 'Z':
  948.       /* merge output */
  949.       if (files_parsed == 0) {
  950.     set_option(OPT_COMPACT, setmode_value, set_val);
  951.       } else {
  952.     fprintf(stderr, "The -Z flag must precede any file arguments\n");
  953.     show_usage();
  954.       }
  955.       break;
  956.     default:
  957.       /* huh? */
  958.       fprintf(stderr, "Unknown option '%c' in <%s>\n", cmd_str[count],
  959.           cmd_str);
  960.       show_usage();
  961.     }
  962.   }
  963. }
  964. #endif /* VMS */
  965.  
  966. /* determine the configuration command, exit if invalid */
  967. void
  968. parse_cmd (cmd_str, set_val, cmd_line)
  969.   char *cmd_str;
  970.   int set_val, cmd_line;
  971. {
  972.   int len, count, did_cmd_parse = FALSE, had_start = FALSE;
  973.   char t2_str[MID_SIZE];
  974.  
  975.   /* clean ends of spaces */
  976.   trim_str(cmd_str);
  977.  
  978.   /* by default, set for both */
  979.   setmode_value = 2;
  980.  
  981.   /* non-command line */
  982.   if (cmd_line == FALSE) {
  983.  
  984.     /* selection? */
  985.     if (strncmp("extract-only ", cmd_str, 13) == 0) {
  986.       setmode_value = 0;
  987.       for (count = 0; count < 13; count++)
  988.     cmd_str[count] = ' ';
  989.       trim_str(cmd_str);
  990.     } else if (strncmp("doc-only ", cmd_str, 9) == 0) {
  991.       setmode_value = 1;
  992.       for (count = 0; count < 9; count++)
  993.     cmd_str[count] = ' ';
  994.       trim_str(cmd_str);
  995.     }
  996.  
  997.   }
  998.  
  999.   /* off? */
  1000.   if (cmd_str[0] == '!') {
  1001.     cmd_str[0] = ' ';
  1002.     trim_str(cmd_str);
  1003.     set_val ^= TRUE;
  1004.     had_start = TRUE;
  1005.   } else {
  1006.     if (strncmp("no-", cmd_str, 3) == 0) {
  1007.       for (count = 0; count < 3; count++)
  1008.     cmd_str[count] = ' ';
  1009.       trim_str(cmd_str);
  1010.       set_val ^= TRUE;
  1011.       had_start = TRUE;
  1012.     } else if (strncmp("no", cmd_str, 2) == 0) {
  1013.       for (count = 0; count < 2; count++)
  1014.     cmd_str[count] = ' ';
  1015.       trim_str(cmd_str);
  1016.       set_val ^= TRUE;
  1017.       had_start = TRUE;
  1018.     }
  1019.   }
  1020.   len = strlen(cmd_str);
  1021.  
  1022.   /* parse actual command */
  1023.   switch (cmd_str[0]) {
  1024.   case '\0':
  1025.   case '#':
  1026.     /* comment */
  1027.     did_cmd_parse = TRUE;
  1028.     break;
  1029.   case 'a':
  1030.     /* ansi C code */
  1031.     if (minmatch_str(cmd_str, "ansi-code", 4)) {
  1032.       did_cmd_parse = TRUE;
  1033.       if (files_parsed > 0) {
  1034.     if (cmd_line) {
  1035.       fprintf(stderr, "Error, ansi-code flag found after file argument\n");
  1036.       exit(1);
  1037.     }
  1038.       } else {
  1039.     set_option(OPT_STDCUSE, setmode_value, set_val);
  1040.       }
  1041.     }
  1042.     break;
  1043.   case 'b':
  1044.     if (minmatch_str(cmd_str, "build-config", 5)) {
  1045.       did_cmd_parse = TRUE;
  1046.       if (cmd_line) {
  1047.     build_rc(CONFIG_FILE);
  1048.     exit(0);
  1049.       } else {
  1050.     cfg_err("warning, the build-config command is unsupported", cmd_line);
  1051.       }
  1052.     } else if (minmatch_str(cmd_str, "break-types", 5) ||
  1053.            minmatch_str(cmd_str, "break-after-types", 5)) {
  1054.       set_option(OPT_TYPEWRAP, setmode_value, set_val);
  1055.       did_cmd_parse = TRUE;
  1056.     }
  1057.     break;
  1058.   case 'c':
  1059.     /* get comments */
  1060.     if (minmatch_str(cmd_str, "comments", 4)) {
  1061.       set_option(OPT_COMMENTS, setmode_value, set_val);
  1062.       did_cmd_parse = TRUE;
  1063.     } else if (count = minmatch_str(cmd_str, "cpp-program", 3)) {
  1064.       did_cmd_parse = TRUE;
  1065.       if (files_parsed > 0) {
  1066.     if (cmd_line) {
  1067.       fprintf(stderr,
  1068.           "Error: cpp-program flag found after file arguments\n");
  1069.       exit(1);
  1070.     }
  1071.       } else {
  1072.     for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1073.       if ((cmd_str[count] == ':') ||
  1074.           (cmd_str[count] == '=')) {
  1075.         count++;
  1076.         break;
  1077.       }
  1078.     }
  1079.     strcpy(tmp_str, cmd_str + count);
  1080.     trim_str(tmp_str);
  1081.     if (strlen(tmp_str) > 0) {
  1082.       strcpy(cpp_prog, tmp_str);
  1083.     } else {
  1084.       cfg_err("warning, blank cpp-program name", cmd_line);
  1085.     }
  1086.       }
  1087.     } else if (count = minmatch_str(cmd_str, "config-file", 4)) {
  1088.       did_cmd_parse = TRUE;
  1089.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1090.     if ((cmd_str[count] == ':') ||
  1091.         (cmd_str[count] == '=')) {
  1092.       count++;
  1093.       break;
  1094.     }
  1095.       }
  1096.       strcpy(tmp_str, cmd_str + count);
  1097.       trim_str(tmp_str);
  1098.       if (strlen(tmp_str) > 0) {
  1099.     parse_config(tmp_str);
  1100.       } else {
  1101.     cfg_err("warning, blank config file name", cmd_line);
  1102.       }
  1103.     }
  1104.     break;
  1105.   case 'd':
  1106.     if (minmatch_str(cmd_str, "dual-output", 4)) {
  1107.       did_cmd_parse = TRUE;
  1108.       if (files_parsed > 0) {
  1109.     if (cmd_line) {
  1110.       fprintf(stderr,
  1111.           "Error, dual-output flag found after file argument\n");
  1112.       exit(1);
  1113.     }
  1114.       } else {
  1115.     set_option(OPT_BOTHUSE, setmode_value, set_val);
  1116.       }
  1117.     } else if (minmatch_str(cmd_str, "discard-names", 4)) {
  1118.       set_option(OPT_NONAMES, setmode_value, set_val);
  1119.       did_cmd_parse = TRUE;
  1120.     } else if (minmatch_str(cmd_str, "doc-mode", 3)) {
  1121.       did_cmd_parse = TRUE;
  1122.       if (files_parsed > 0) {
  1123.     if (cmd_line) {
  1124.       fprintf(stderr, "Error, doc-mode flag found after file argument\n");
  1125.       exit(1);
  1126.     }
  1127.       } else {
  1128.     doc_extract = DOC_NORMAL;
  1129.       }
  1130.     } else if (count = minmatch_str(cmd_str, "define", 3)) {
  1131.       did_cmd_parse = TRUE;
  1132.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1133.     if ((cmd_str[count] == ':') ||
  1134.         (cmd_str[count] == '=')) {
  1135.       count++;
  1136.       break;
  1137.     }
  1138.       }
  1139.       strcpy(tmp_str, cmd_str + count);
  1140.       trim_str(tmp_str);
  1141.       if (strlen(tmp_str) > 0) {
  1142.     sprintf(cmd_str, "%s%s", DEF_LEADER, tmp_str);
  1143.     add_macro(setmode_value, cmd_str);
  1144.       } else {
  1145.     cfg_err("warning, blank define command", cmd_line);
  1146.       }
  1147.     }
  1148.     break;
  1149.   case 'e':
  1150.     if (minmatch_str(cmd_str, "externs", 4)) {
  1151.       /* extern prepending */
  1152.       did_cmd_parse = TRUE;
  1153.       set_option(OPT_EXTERNS, setmode_value, set_val);
  1154.     } else if (minmatch_str(cmd_str, "extract-mode", 3)) {
  1155.       /* extract mode */
  1156.       did_cmd_parse = TRUE;
  1157.       if (files_parsed > 0) {
  1158.     if (cmd_line) {
  1159.       fprintf(stderr, "Error, extract-mode found after file argument\n");
  1160.       exit(1);
  1161.     }
  1162.       } else {
  1163.     doc_extract = DOC_NONE;
  1164.       }
  1165.     }
  1166.     break;
  1167.   case 'f':
  1168.     if (minmatch_str(cmd_str, "first-comments", 4)) {
  1169.       /* grabs first comments */
  1170.       did_cmd_parse = TRUE;
  1171.       set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
  1172.     } else if (minmatch_str(cmd_str, "filename", 4)) {
  1173.       /* prepend file name */
  1174.       did_cmd_parse = TRUE;
  1175.       set_option(OPT_PREPEND, setmode_value, set_val);
  1176.     } else if (strncmp("font", cmd_str, 4) == 0) {
  1177.       /* fonts */
  1178.       did_cmd_parse = TRUE;
  1179.       if (files_parsed > 0) {
  1180.     if (cmd_line) {
  1181.       fprintf(stderr, "Error, -font flag found after file argument\n");
  1182.       exit(1);
  1183.     }
  1184.       } else {
  1185.     switch (cmd_str[5]) {
  1186.     case '1':
  1187.     case 't':
  1188.     case 'T':
  1189.       /* title */
  1190.       if ((cmd_str[6] != '\0') &&
  1191.           (isalnum(cmd_str[7]) &&
  1192.            (isalnum(cmd_str[8]) ||
  1193.         (cmd_str[8] == '\0')))) {
  1194.         ft_title[0] = cmd_str[7];
  1195.         ft_title[1] = cmd_str[8];
  1196.         ft_title[2] = '\0';
  1197.       } else {
  1198.         fprintf(stderr, "warning: improper font type in:\n");
  1199.         fprintf(stderr, "   ==> %s\n", cmd_str);
  1200.         goto prop_font;
  1201.       }
  1202.       break;
  1203.     case '2':
  1204.     case 'c':
  1205.     case 'C':
  1206.       /* comment */
  1207.       if ((cmd_str[6] != '\0') &&
  1208.           (isalnum(cmd_str[7]) &&
  1209.            (isalnum(cmd_str[8]) ||
  1210.         (cmd_str[8] == '\0')))) {
  1211.         ft_comment[0] = cmd_str[7];
  1212.         ft_comment[1] = cmd_str[8];
  1213.         ft_comment[2] = '\0';
  1214.       } else {
  1215.         fprintf(stderr, "warning: improper font type in:\n");
  1216.         fprintf(stderr, "   ==> %s\n", cmd_str);
  1217.         goto prop_font;
  1218.       }
  1219.       break;
  1220.     case '3':
  1221.     case 'n':
  1222.     case 'N':
  1223.       /* function name */
  1224.       if ((cmd_str[6] != '\0') &&
  1225.           (isalnum(cmd_str[7]) &&
  1226.            (isalnum(cmd_str[8]) ||
  1227.         (cmd_str[8] == '\0')))) {
  1228.         ft_name[0] = cmd_str[7];
  1229.         ft_name[1] = cmd_str[8];
  1230.         ft_name[2] = '\0';
  1231.       } else {
  1232.         fprintf(stderr, "warning: improper font type in:\n");
  1233.         fprintf(stderr, "   ==> %s\n", cmd_str);
  1234.         goto prop_font;
  1235.       }
  1236.       break;
  1237.     case '4':
  1238.     case 'p':
  1239.     case 'P':
  1240.       /* parameter font */
  1241.       if ((cmd_str[6] != '\0') &&
  1242.           (isalnum(cmd_str[7]) &&
  1243.            (isalnum(cmd_str[8]) ||
  1244.         (cmd_str[8] == '\0')))) {
  1245.         ft_plist[0] = cmd_str[7];
  1246.         ft_plist[1] = cmd_str[8];
  1247.         ft_plist[2] = '\0';
  1248.       } else {
  1249.         fprintf(stderr, "warning: improper font type in:\n");
  1250.         fprintf(stderr, "   ==> %s\n", cmd_str);
  1251.         goto prop_font;
  1252.       }
  1253.       break;
  1254.     default:
  1255.       /* oops */
  1256.       fprintf(stderr, "warning: font format invalid\n");
  1257.     prop_font:
  1258.       if (cmd_line) {
  1259.         fprintf(stderr, "Proper format:  -font-%%-##\n");
  1260.       } else {
  1261.         fprintf(stderr, "Proper format:  font %% ##\n");
  1262.       }
  1263.       fprintf(stderr, "Where %% = one of:\n");
  1264.       fprintf(stderr, "     '1' or 't'  - font for titles\n");
  1265.       fprintf(stderr, "     '2' or 'c'  - comment font\n");
  1266.       fprintf(stderr, "     '3' or 'n'  - function name font\n");
  1267.       fprintf(stderr, "     '4' or 'p'  - parameter list font\n");
  1268.       fprintf(stderr, "and ## is the one or two character roff font.\n");
  1269.       break;
  1270.     }
  1271.       }
  1272.     }
  1273.     break;
  1274.   case 'h':
  1275.     /* header string */
  1276.     if (count = minmatch_str(cmd_str, "header-string", 4)) {
  1277.       did_cmd_parse = TRUE;
  1278.       /* can only replace on the command line */
  1279.       if ((header_string[0] != '\0') && !cmd_line) break;
  1280.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1281.     if ((cmd_str[count] == ':') ||
  1282.         (cmd_str[count] == '=')) {
  1283.       count++;
  1284.       break;
  1285.     }
  1286.       }
  1287.       strcpy(tmp_str, cmd_str + count);
  1288.       trim_str(tmp_str);
  1289.       if (strlen(tmp_str) > 0) {
  1290.     strcpy(header_string, tmp_str);
  1291.       } else {
  1292.     cfg_err("warning: blank header-string command", cmd_line);
  1293.       }
  1294.     }
  1295.     break;
  1296.   case 'i':
  1297.     /* include file */
  1298.     if (count = minmatch_str(cmd_str, "include", 3)) {
  1299.       did_cmd_parse = TRUE;
  1300.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1301.     if ((cmd_str[count] == ':') ||
  1302.         (cmd_str[count] == '=')) {
  1303.       count++;
  1304.       break;
  1305.     }
  1306.       }
  1307.       strcpy(tmp_str, cmd_str + count);
  1308.       trim_str(tmp_str);
  1309.       if (strlen(tmp_str) > 0) {
  1310.     sprintf(cmd_str, "%s%s", INC_LEADER, tmp_str);
  1311.     add_macro(setmode_value, cmd_str);
  1312.       } else {
  1313.     cfg_err("warning: blank include command", cmd_line);
  1314.       }
  1315.     }
  1316.     break;
  1317.   case 'm':
  1318.     /* multiple comments */
  1319.     if (minmatch_str(cmd_str, "multi-comments", 4) ||
  1320.     minmatch_str(cmd_str, "multiple-comments", 4)) {
  1321.       did_cmd_parse = TRUE;
  1322.       set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
  1323.     } else if (minmatch_str(cmd_str, "merge-output", 5)) {
  1324.       did_cmd_parse = TRUE;
  1325.       if (files_parsed > 0) {
  1326.     if (cmd_line) {
  1327.       fprintf(stderr,
  1328.           "Error: merge-output flag found after file argument\n");
  1329.       exit(1);
  1330.     }
  1331.       } else {
  1332.     set_option(OPT_COMPACT, setmode_value, set_val);
  1333.       }
  1334.     }
  1335.     break;
  1336.   case 'o':
  1337.     /* output file */
  1338.     if (count = minmatch_str(cmd_str, "output-file", 3)) {
  1339.       did_cmd_parse = TRUE;
  1340.       if (files_parsed > 0) {
  1341.     if (cmd_line) {
  1342.       fprintf(stderr,
  1343.           "Error: output-file flag found after file arguments\n");
  1344.       exit(1);
  1345.     }
  1346.       } else {
  1347.     for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1348.       if ((cmd_str[count] == ':') ||
  1349.           (cmd_str[count] == '=')) {
  1350.         count++;
  1351.         break;
  1352.       }
  1353.     }
  1354.     strcpy(tmp_str, cmd_str + count);
  1355.     trim_str(tmp_str);
  1356.     if (strlen(tmp_str) > 0) {
  1357.       if ((setmode_value % 2) == 0) {
  1358.         strcpy(output_file[0], tmp_str);
  1359.       }
  1360.       if (setmode_value != 0) {
  1361.         strcpy(output_file[1], tmp_str);
  1362.       }
  1363.       out_filenum = 2;
  1364.     } else if (!cmd_line) {
  1365.       cfg_err("warning, blank output-file specifier", cmd_line);
  1366.     } else {
  1367.       out_filenum = 1;
  1368.     }
  1369.       }
  1370.     }
  1371.     break;
  1372.   case 'p':
  1373.     /* prepend the file name to the output */
  1374.     if (minmatch_str(cmd_str, "prepend-filename", 4)) {
  1375.       did_cmd_parse = TRUE;
  1376.       set_option(OPT_PREPEND, setmode_value, set_val);
  1377.     }
  1378.     break;
  1379.   case 'r':
  1380.     if (strncmp(cmd_str, "replace", 7) == 0) {
  1381.  
  1382.       if (cmd_line) {
  1383.     fprintf(stderr,
  1384.         "Error, -replace is not a valid command line option\n");
  1385.     exit(1);
  1386.       }
  1387.  
  1388.       /* check type */
  1389.       if (strncmp("all ", cmd_str + 8, 4) == 0) {
  1390.     len = 12;
  1391.     count = SUBST_FULL; 
  1392.       } else if (strncmp("type ", cmd_str + 8, 5) == 0) {
  1393.     len = 13;
  1394.     count = SUBST_TYPE;
  1395.       } else if (strncmp("name ", cmd_str + 8, 5) == 0) {
  1396.     len = 13;
  1397.     count = SUBST_NAME;
  1398.       } else if (strncmp("variable ", cmd_str + 8, 9) == 0) {
  1399.     len = 17;
  1400.     count = SUBST_NAME;
  1401.       } else {
  1402.     cfg_err("warning, bad replace format", cmd_line);
  1403.     fprintf(stderr, "   ==> %s\n", cmd_str);
  1404.     count = len = 0;
  1405.     did_cmd_parse = TRUE;
  1406.       }
  1407.  
  1408.       /* do it */
  1409.       if (did_cmd_parse == FALSE) {
  1410.  
  1411.     did_cmd_parse = TRUE;
  1412.     if ((set_val = copy_str(tmp_str, cmd_str + len)) == -1) {
  1413.       cfg_err("warning, bad replace format", cmd_line);
  1414.       fprintf(stderr, "   ==> %s\n", cmd_str);
  1415.       break;
  1416.     }
  1417.     len += set_val;
  1418.     if ((set_val = copy_str(t2_str, cmd_str + len)) == -1) {
  1419.       cfg_err("warning, bad replace format", cmd_line);
  1420.       fprintf(stderr, "   ==> %s\n", cmd_str);
  1421.       break;
  1422.     }
  1423.  
  1424.     /* add substitution macro */
  1425.     add_subst(count, setmode_value, tmp_str, t2_str);
  1426.  
  1427.       }
  1428.  
  1429.     } else if (minmatch_str(cmd_str, "read-config", 4)) {
  1430.       if (cmd_line) {
  1431.     fprintf(stderr, "The -read-config flag must be the first argument\n");
  1432.     show_usage();
  1433.       } else {
  1434.     cfg_err("The -read-config command is not supported", cmd_line);
  1435.     exit(1);
  1436.       }
  1437.     } else if (minmatch_str(cmd_str, "remove-names", 3)) {
  1438.       /* remove variables? */
  1439.       set_option(OPT_NONAMES, setmode_value, set_val);
  1440.       did_cmd_parse = TRUE;
  1441.     } else if (minmatch_str(cmd_str, "roff-mode", 4)) {
  1442.  
  1443.       did_cmd_parse = TRUE;
  1444.       if (files_parsed > 0) {
  1445.     if (cmd_line) {
  1446.       fprintf(stderr, "Error: -roff-mode found after file argument\n");
  1447.       exit(1);
  1448.     }
  1449.       } else {
  1450.     doc_extract = DOC_ROFF;
  1451.       }
  1452.  
  1453.     }
  1454.     break;
  1455.   case 's':
  1456.     if ((count = minmatch_str(cmd_str, "statics", 4))) {
  1457.  
  1458.       /* statics? */
  1459.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1460.     if ((cmd_str[count] == ':') ||
  1461.         (cmd_str[count] == '=')) {
  1462.       count++;
  1463.       break;
  1464.     }
  1465.       }
  1466.       strcpy(tmp_str, cmd_str + count);
  1467.       trim_str(tmp_str);
  1468.       if (strlen(tmp_str) > 0) {
  1469.  
  1470.     /* which? */
  1471.     switch(tmp_str[0]) {
  1472.     case 'a':
  1473.       /* all statics are allowed */
  1474.       set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  1475.       did_cmd_parse = TRUE;
  1476.       break;
  1477.     case 'o':
  1478.       /* only statics are allowed */
  1479.       set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
  1480.       did_cmd_parse = TRUE;
  1481.       break;
  1482.     case 'n':
  1483.       /* no statics are allowed */
  1484.       set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  1485.       did_cmd_parse = TRUE;
  1486.       break;
  1487.     default:
  1488.       /* not one that I know of */
  1489.       break;
  1490.     }
  1491.  
  1492.       } else {
  1493.  
  1494.     /* defaults */
  1495.     if (set_val) {
  1496.       set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
  1497.     } else {
  1498.       set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
  1499.     }
  1500.     did_cmd_parse = TRUE;
  1501.  
  1502.       }
  1503.  
  1504.     } else if (minmatch_str(cmd_str, "sort-all", 4)) {
  1505.       /* sort? */
  1506.       did_cmd_parse = TRUE;
  1507.       if (set_val) {
  1508.     set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
  1509.       } else {
  1510.     set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  1511.       }
  1512.     } else if (minmatch_str(cmd_str, "show-all", 4) ||
  1513.            minmatch_str(cmd_str, "show-anyway", 4)) {
  1514.       /* ANSI? */
  1515.       set_option(OPT_SHOWANYWAY, setmode_value, set_val);
  1516.       did_cmd_parse = TRUE;
  1517.     } else if (minmatch_str(cmd_str, "settings", 3)) {
  1518.       did_cmd_parse = TRUE;
  1519.       if (cmd_line) {
  1520.     show_settings();
  1521.       } else {
  1522.     cfg_err("warning, the -settings command is unsupported", cmd_line);
  1523.       }
  1524.     } else if (minmatch_str(cmd_str, "system-build", 6)) {
  1525.       did_cmd_parse = TRUE;
  1526.       if (cmd_line) {
  1527.     build_rc(SYS_CONFIG);
  1528.     exit(0);
  1529.       } else {
  1530.     cfg_err("warning, the -system-build command is unsupported", cmd_line);
  1531.       }
  1532.     } else if (minmatch_str(cmd_str, "sort-by-files", 6)) {
  1533.       /* file sort? */
  1534.       did_cmd_parse = TRUE;
  1535.       if (global_opts[setmode_value == 1][OPT_SORTMODE] != SORT_ALL) {
  1536.     if (set_val) {
  1537.       set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
  1538.     } else {
  1539.       set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
  1540.     }
  1541.       }
  1542.     } else if (minmatch_str(cmd_str, "single-comments", 3)) {
  1543.       /* !multiple comments? */
  1544.       did_cmd_parse = TRUE;
  1545.       set_option(OPT_SINGLECOMMENTS, setmode_value, set_val);
  1546.     }
  1547.     break;
  1548.   case 't':
  1549.     if (count = minmatch_str(cmd_str, "tab-width", 3)) {
  1550.       int tab_width;
  1551.       did_cmd_parse = TRUE;
  1552.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1553.     if ((cmd_str[count] == ':') ||
  1554.         (cmd_str[count] == '=')) {
  1555.       count++;
  1556.       break;
  1557.     }
  1558.       }
  1559.       strcpy(tmp_str, cmd_str + count);
  1560.       trim_str(tmp_str);
  1561.       if (sscanf(tmp_str, "%d", &tab_width) != 1) {
  1562.     tab_width = 0;
  1563.       }
  1564.       set_option(OPT_TABWIDTH, setmode_value, tab_width);
  1565.     } else if (minmatch_str(cmd_str, "troff-mode", 4)) {
  1566.       did_cmd_parse = TRUE;
  1567.       if (files_parsed > 0) {
  1568.     if (cmd_line) {
  1569.       fprintf(stderr, "Error: -troff-mode found after file argument\n");
  1570.       exit(1);
  1571.     }
  1572.       } else {
  1573.     doc_extract = DOC_ROFF;
  1574.       }
  1575.     }
  1576.     break;
  1577.   case 'u':
  1578.     /* undefine macro */
  1579.     if (count = minmatch_str(cmd_str, "undefine", 3)) {
  1580.       did_cmd_parse = TRUE;
  1581.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1582.     if ((cmd_str[count] == ':') ||
  1583.         (cmd_str[count] == '=')) {
  1584.       count++;
  1585.       break;
  1586.     }
  1587.       }
  1588.       strcpy(tmp_str, cmd_str + count);
  1589.       trim_str(tmp_str);
  1590.       if (strlen(tmp_str) > 0) {
  1591.     if (removed_macro(setmode_value, tmp_str) != TRUE) {
  1592.       sprintf(cmd_str, "%s%s", UNDEF_LEADER, tmp_str);
  1593.       add_macro(setmode_value, cmd_str);
  1594.     }
  1595.       } else {
  1596.     cfg_err("warning: blank undefine", cmd_line);
  1597.       }
  1598.     }
  1599.     break;
  1600.   case 'v':
  1601.     if (minmatch_str(cmd_str, "version-info", 3)) {
  1602.       did_cmd_parse = TRUE;
  1603.       if (cmd_line) {
  1604.     show_version();
  1605.     exit(0);
  1606.       } else {
  1607.     cfg_err("warning, the -version-info command is unsupported", cmd_line);
  1608.       }
  1609.     }
  1610.     break;
  1611.   case 'w':
  1612.     /* wrapping */
  1613.     if (count = minmatch_str(cmd_str, "wrap-parameters", 4)) {
  1614.       did_cmd_parse = TRUE;
  1615.       for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
  1616.     if ((cmd_str[count] == ':') ||
  1617.         (cmd_str[count] == '=')) {
  1618.       count++;
  1619.       break;
  1620.     }
  1621.       }
  1622.       strcpy(tmp_str, cmd_str + count);
  1623.       trim_str(tmp_str);
  1624.       count = 0;
  1625.       if (isdigit(tmp_str[count])) {
  1626.     /* use given */
  1627.     int wrap_point = 0;
  1628.     for (; isdigit(tmp_str[count]); count++) {
  1629.       wrap_point *= 10;
  1630.       wrap_point += (tmp_str[count] - '0');
  1631.     }
  1632.     count--;
  1633.     set_option(OPT_WRAPPOINT, setmode_value, wrap_point);
  1634.       } else if (set_val) {
  1635.     /* default */
  1636.     set_option(OPT_WRAPPOINT, setmode_value, 72);
  1637.       } else {
  1638.     /* off */
  1639.     set_option(OPT_WRAPPOINT, setmode_value, 0);
  1640.       }
  1641.     }
  1642.     break;
  1643.   case 'y':
  1644.     /* get comments */
  1645.     if (minmatch_str(cmd_str, "yank-comments", 4)) {
  1646.       did_cmd_parse = TRUE;
  1647.       set_option(OPT_COMMENTS, setmode_value, set_val);
  1648.     }
  1649.     break;
  1650.   default:
  1651.     /* huh? */
  1652.     break;
  1653.   }
  1654.  
  1655.   /* find it? */
  1656.   if (did_cmd_parse == FALSE) {
  1657. #ifndef VMS
  1658.     if (!cmd_line || (had_start == TRUE)) {
  1659. #endif /* VMS */
  1660.       cfg_err("unknown option encountered", cmd_line);
  1661.       fprintf(stderr, "   ==> %s\n", cmd_str);
  1662.       exit(1);
  1663. #ifndef VMS
  1664.     } else {
  1665.       singlechar_cmds(cmd_str, set_val);
  1666.     }
  1667. #endif /* VMS */
  1668.   }
  1669. }
  1670.  
  1671. /* function to parse the configuration file */
  1672. void
  1673. parse_config (conf_fname)
  1674.   char *conf_fname;
  1675. {
  1676.   char conf_data[MID_SIZE], tmp_fname[FNAME_SIZE];
  1677.   FILE *conf_fp;
  1678.  
  1679.   /* check input */
  1680.   if ((conf_fp = fopen(conf_fname, "r")) == NULL) return;
  1681.   strcpy(tmp_fname, cur_cfg_file);
  1682.   strcpy(cur_cfg_file, conf_fname);
  1683.  
  1684.   /* read it all */
  1685.   while (!feof(conf_fp)) {
  1686.  
  1687.     /* get a line */
  1688.     conf_data[0] = '\0';
  1689.     if (fgets(conf_data, MID_SIZE, conf_fp) != NULL) {
  1690.       /* parse it */
  1691.       parse_cmd(conf_data, TRUE, FALSE);
  1692.     }
  1693.  
  1694.   }
  1695.  
  1696.   /* done */
  1697.   fclose(conf_fp);
  1698.   strcpy(cur_cfg_file, tmp_fname);
  1699. }
  1700.  
  1701. /* send a system error message */
  1702. void
  1703. err_msg(estr)
  1704.   char *estr;
  1705. {
  1706. #ifdef NO_PERROR
  1707.   fprintf(stderr, "%s: %s\n", prog_name, estr);
  1708. #else
  1709.   fprintf(stderr, "%s\n", estr);
  1710.   perror(prog_name);
  1711. #endif /* NO_PERROR */
  1712. }
  1713.  
  1714. /* send a message that their was a syntax error */
  1715. void
  1716. syntax_err(estr)
  1717.   char *estr;
  1718. {
  1719.   /* use messages similar to gcc error messages */
  1720.   fprintf(stderr, "%s:%d: %s\n", errout_filename, line_count, estr);
  1721. }
  1722.  
  1723. /* routine to check return value of fputs */
  1724. void
  1725. fput_string (outstr, filep)
  1726.   char *outstr;
  1727.   FILE *filep;
  1728. {
  1729.   /* check the output of fputs */
  1730.   if (fputs(outstr, filep) == EOF) {
  1731.     err_msg("unable to write to file");
  1732.     exit(1);
  1733.   }
  1734. }
  1735.  
  1736. /* quickie function to distinquish proper switches */
  1737. int
  1738. is_switch (ch)
  1739.   int ch;
  1740. {
  1741.   if (ch == '-') return(TRUE);
  1742.   if (ch == '+') return(TRUE);
  1743. #ifdef VMS
  1744.   if (ch == '/') return(TRUE);
  1745. #endif /* VMS */
  1746.   return(FALSE);
  1747. }
  1748.  
  1749. /* call the external routine out_char() and send out all characters */
  1750. void
  1751. out_str(omode, str)
  1752.   int omode;
  1753.   char *str;
  1754. {
  1755.   /* simple function */
  1756.   if (str != NULL) {
  1757.     while (*str != '\0') {
  1758.       out_char(omode, *str);
  1759.       str++;
  1760.     }
  1761.   }
  1762. }
  1763.  
  1764. /* output given function prototype */
  1765. void
  1766. out_proto(omode, f_ptr, mode, do_comments)
  1767.   int omode;
  1768.   P_PROTO f_ptr;
  1769.   int mode, do_comments;
  1770. {
  1771.   char *ch_out, tempstr[MID_SIZE];
  1772.   int did_leader = FALSE;
  1773.   int outch_cnt = 0, leader_cnt;
  1774.   int wrap_point = get_option(OPT_WRAPPOINT);
  1775.  
  1776.   /* stupidity? */
  1777.   if (f_ptr == NULL) return;
  1778.  
  1779.   /* initial comment output */
  1780.   if (get_option(OPT_FIRSTCOMMENT) &&
  1781.       (start_comment[0] != '\0')) {
  1782.  
  1783.     /* first comment? */
  1784.     strcpy(tempstr, "/*");
  1785.     if (get_option(OPT_PREPEND)) {
  1786.       strcat(tempstr, " ");
  1787.       strcat(tempstr, file_name);
  1788.       strcat(tempstr, ":");
  1789.     }
  1790.     send_first_comment(tempstr);
  1791.     did_leader = TRUE;
  1792.     start_comment[0] = '\0';
  1793.   }
  1794.  
  1795.   /* preamble? */
  1796.   if (doc_extract != DOC_NONE) {
  1797.     if (dont_space == FALSE) {
  1798.       if (doc_extract != DOC_ROFF) {
  1799.     out_char(omode, '\n');
  1800.     out_char(omode, '\n');
  1801.       } else {
  1802.     out_str(omode, ".sp 2\n");
  1803.       }
  1804.     } else if (doc_extract == DOC_ROFF) {
  1805.       init_roff(omode);
  1806.     }
  1807.     dont_space = FALSE;
  1808.     if (doc_extract != DOC_ROFF) {
  1809.       out_str(omode, "Function: ");
  1810.       out_str(omode, f_ptr->name);
  1811.       out_str(omode, "\nFile:     ");
  1812.     } else {
  1813.       if (start_block == FALSE) {
  1814.     out_str(omode, ".KS\n");
  1815.       } else {
  1816.     start_block = FALSE;
  1817.       }
  1818.       out_str(omode, ".nf\n");
  1819.       out_str(omode, "\\f1Function: \\f3");
  1820.       out_str(omode, f_ptr->name);
  1821.       out_str(omode, "\n\\f1File:     \\f3");
  1822.     }
  1823.     out_str(omode, f_ptr->fname);
  1824.     out_char(omode, '\n');
  1825.   }
  1826.  
  1827.   /* preceeding comment? */
  1828.   if (do_comments) {
  1829.     if (doc_extract != DOC_ROFF) {
  1830.       out_char(omode, '\n');
  1831.       if (f_ptr->comment != NULL) {
  1832.     out_str(omode, f_ptr->comment);
  1833.     out_char(omode, '\n');
  1834.       }
  1835.     } else {
  1836.       out_str(omode, ".sp\n\\f2");
  1837.       out_str(omode, f_ptr->comment);
  1838.       out_char(omode, '\n');
  1839.     }
  1840.   } else if ((doc_extract != DOC_NONE) ||
  1841.          (total_out == 0) ||
  1842.          did_leader) {
  1843.     if (doc_extract != DOC_ROFF) {
  1844.       out_char(omode, '\n');
  1845.     } else {
  1846.       out_str(omode, ".sp\n");
  1847.     }
  1848.   }
  1849.  
  1850.   /* fill mode for troff? */
  1851.   if (doc_extract == DOC_ROFF) {
  1852.     out_str(omode, ".fi\n");
  1853.     out_str(omode, ".in +0.5i\n");
  1854.     out_str(omode, ".ti -0.5i\n");
  1855.   }
  1856.  
  1857.   /* show the full function name and type */
  1858.   if (doc_extract == DOC_ROFF) {
  1859.     out_str(omode, "\\f3");
  1860.     out_str(omode, f_ptr->ftype);
  1861.     out_str(omode, " ( \\c\n\\f4");
  1862.   } else {
  1863.     if (get_option(OPT_TYPEWRAP)) {
  1864.       char *second_half;
  1865.  
  1866.       /* split at function name */
  1867.       if (second_half = strstr(f_ptr->ftype, f_ptr->name)) {
  1868.     outch_cnt = strlen(second_half);
  1869.     for (ch_out = f_ptr->ftype;
  1870.          (ch_out != second_half) &&
  1871.          ((*ch_out != ' ') ||
  1872.           (ch_out != second_half - 1));
  1873.          ch_out++) {
  1874.       out_char(omode, *ch_out);
  1875.     }
  1876.     out_char(omode, '\n');
  1877.     out_str(omode, second_half);
  1878.       } else {
  1879.     /* normal output */
  1880.     outch_cnt = strlen(f_ptr->ftype);
  1881.     out_str(omode, f_ptr->ftype);
  1882.       }
  1883.     } else {
  1884.       /* normal output */
  1885.       outch_cnt = strlen(f_ptr->ftype);
  1886.       out_str(omode, f_ptr->ftype);
  1887.     }
  1888.     if (get_option(OPT_COMPACT)) {
  1889.       out_str(omode, " PL_((");
  1890.       outch_cnt += 6;
  1891.     } else {
  1892.       out_str(omode, " (");
  1893.       outch_cnt += 2;
  1894.     }
  1895.   }
  1896.   leader_cnt = outch_cnt + 1;
  1897.   
  1898.   if (mode != MODE_OLDC) {
  1899.  
  1900.     /* begin comment? */
  1901.     if (mode == MODE_COMMENT) {
  1902.       out_str(omode, "/*");
  1903.       outch_cnt += 2;
  1904.     }
  1905.  
  1906.     /* prototype list */
  1907.     if (doc_extract == DOC_ROFF) {
  1908.  
  1909.       /* break at each variable */
  1910.       for (ch_out = f_ptr->plist;
  1911.        *ch_out != '\0';
  1912.        ch_out++) {
  1913.  
  1914.     /* send out list; breaking for ','s */
  1915.     out_char(omode, *ch_out);
  1916.     if (*ch_out == ',') {
  1917.       out_str(omode, "\\c\n");
  1918.     }
  1919.       }
  1920.  
  1921.     } else if ((wrap_point > 0) &&
  1922.            (f_ptr->plist != NULL) &&
  1923.            (f_ptr->plist[0] != '\0') &&
  1924.            (strlen(f_ptr->plist) + outch_cnt > wrap_point - 1)) {
  1925.       char *next_space;
  1926.  
  1927.       /* break at appropriate positions */
  1928.       ch_out = f_ptr->plist;
  1929.       next_space = index(f_ptr->plist, ' ');
  1930.       do {
  1931.  
  1932.     /* check for break point */
  1933.     if (next_space == NULL) {
  1934.  
  1935.       /* wrap point within reach? */
  1936.       if (strlen(ch_out) + outch_cnt > wrap_point) {
  1937.         out_char(omode, '\n');
  1938.         for (outch_cnt = 0;
  1939.          outch_cnt < leader_cnt - 1;
  1940.          outch_cnt++) {
  1941.           out_char(omode, ' ');
  1942.         }
  1943.       }
  1944.       out_char(omode, ' ');
  1945.       out_str(omode, ch_out);
  1946.       ch_out = NULL;
  1947.  
  1948.     } else {
  1949.  
  1950.       /* wrap point within reach? */
  1951.       if (next_space - ch_out + outch_cnt > wrap_point) {
  1952.         out_char(omode, '\n');
  1953.         for (outch_cnt = 0;
  1954.          outch_cnt < leader_cnt;
  1955.          outch_cnt++) {
  1956.           out_char(omode, ' ');
  1957.         }
  1958.       } else {
  1959.         out_char(omode, ' ');
  1960.         outch_cnt++;
  1961.       }
  1962.       for (; ch_out < next_space; ch_out++) {
  1963.         out_char(omode, *ch_out);
  1964.         outch_cnt++;
  1965.       }
  1966.       ch_out = next_space + 1;
  1967.  
  1968.       /* determine the next space location */
  1969.       next_space = index(next_space + 1, ' ');
  1970.  
  1971.     }
  1972.  
  1973.       } while (ch_out != NULL);
  1974.       out_char(omode, ' ');
  1975.  
  1976.     } else {
  1977.  
  1978.       /* send out parameter list */
  1979.       out_char(omode, ' ');
  1980.       out_str(omode, f_ptr->plist);
  1981.       if ((f_ptr->plist) &&
  1982.       (f_ptr->plist[0] != '\0')) {
  1983.     out_char(omode, ' ');
  1984.       }
  1985.  
  1986.     }
  1987.  
  1988.     /* end comments? */
  1989.     if (mode == MODE_COMMENT) {
  1990.       out_str(omode, "*/");
  1991.     }
  1992.  
  1993.   }
  1994.  
  1995.   /* close up */
  1996.   if (doc_extract == DOC_ROFF) {
  1997.     out_str(omode, "\\f3 );\n");
  1998.   } else {
  1999.     if (get_option(OPT_COMPACT)) {
  2000.       out_char(omode, ')');
  2001.     }
  2002.     out_str(omode, ");\n");
  2003.   }
  2004.  
  2005.   /* turn off fill for troff */
  2006.   if (doc_extract == DOC_ROFF) {
  2007.     out_str(omode, ".nf\n");
  2008.     out_str(omode, ".in -0.5i\n");
  2009.     out_str(omode, ".KE\n");
  2010.   }
  2011. }
  2012.  
  2013. /* set home config file path indicating success */
  2014. static int
  2015. set_home_config()
  2016. {
  2017. #ifndef VAXC
  2018.   struct passwd *pwtemp = NULL;
  2019. #endif /* VAXC */
  2020.   char home_file[MID_SIZE];
  2021.  
  2022.   if (getenv("HOME") != NULL) {
  2023.     strcpy(home_file, (char *)getenv("HOME"));
  2024. #ifndef VAXC
  2025.   } else if ((pwtemp = getpwuid(getuid())) != NULL) {
  2026.     strcpy(home_file, pwtemp->pw_dir);
  2027. #endif /* VAXC */
  2028.   } else {
  2029. #ifdef VMS
  2030.     strcpy(home_file, "sys$login:");
  2031. #else
  2032.     /* oops */
  2033.     return(FALSE);
  2034. #endif /* VMS */
  2035.   }
  2036.  
  2037.   /* build the file */
  2038.   strcat(home_file, DIR_SEPARATOR);
  2039.   strcat(home_file, CONFIG_FILE);
  2040.  
  2041.   /* record it */
  2042.   strcpy(tmp_str, home_file);
  2043.   return(TRUE);
  2044. }
  2045.  
  2046. /* Create test file for varargs and FILE test */
  2047. static int
  2048. bld_testfile(fname)
  2049.   char *fname;
  2050. {
  2051.   FILE *fp;
  2052.  
  2053.   if ((fp = fopen(fname, "w")) == NULL) {
  2054.     sprintf(tmp_str, "Error opening varargs test file <%s>", fname);
  2055.     err_msg(tmp_str);
  2056.     return(TRUE);
  2057.   }
  2058.   fput_string("#include <stdio.h>\n", fp);
  2059.   fput_string("#include <varargs.h>\n", fp);
  2060.   fput_string("int function1(va_alist)\nva_dcl\n", fp);
  2061.   fput_string("{ /* empty function */ }\n", fp);
  2062.   fput_string("int function2(fstrct)\nFILE fstrct;\n", fp);
  2063.   fput_string("{ /* empty function */ }\n", fp);
  2064.   if (fclose(fp) == EOF) {
  2065.     sprintf(tmp_str, "Error closing varargs test file <%s>", fname);
  2066.     err_msg(tmp_str);
  2067.     return(TRUE);
  2068.   }
  2069.   return(FALSE);
  2070. }
  2071.  
  2072. /* search for expanded value of the varargs setup */
  2073. int
  2074. vargs_find ()
  2075. {
  2076.   char sys_cmd[MID_SIZE], tmpfname[MID_SIZE];
  2077.   char t_instr[MID_SIZE], t_outstr[MID_SIZE];
  2078.   int hold = FALSE, type_select = 0;
  2079.   extern int dont_stop;
  2080.  
  2081.   /* build temp file name */
  2082.   sprintf(tmpfname, TMPFILE_FMT, getpid());
  2083.  
  2084.   /* generate it */
  2085.   if (bld_testfile(tmpfname)) {
  2086.     return(TRUE);
  2087.   }
  2088.  
  2089.   /* launch a CPP process */
  2090.   sprintf(sys_cmd, "%s %s", cpp_prog, tmpfname);
  2091.   if ((fpin = open_input(sys_cmd, "r")) == NULL) {
  2092.     sprintf(tmp_str, "unable to open CPP \"pipe\" to file <%s>",
  2093.        tmpfname);
  2094.     err_msg(tmp_str);
  2095.     return(TRUE);
  2096.   }
  2097.  
  2098.   /* now parse it */
  2099.   dont_stop = TRUE;
  2100.   parse_file();
  2101.   dont_stop = FALSE;
  2102.   close_input(fpin);
  2103.   unlink(tmpfname);
  2104.   fpin = NULL;
  2105.  
  2106.   /* retrieve the info */
  2107.   while (proto_list != NULL) {
  2108.  
  2109.     /* get proper function */
  2110.     if (strcmp(proto_list->name, "function1") == 0) {
  2111.       /* varargs */
  2112.       if (strcmp(proto_list->plist, "...") == 0) goto skip_it;
  2113.       strcpy(t_instr, proto_list->plist);
  2114.       strcpy(t_outstr, "...");
  2115.       type_select = SUBST_FULL;
  2116.     } else if (strcmp(proto_list->name, "function2") == 0) {
  2117.       /* FILE structure */
  2118.       for (type_select = strlen(proto_list->plist) - 1;
  2119.        type_select > 0;
  2120.        type_select--) {
  2121.     if (proto_list->plist[type_select] == ' ') {
  2122.       proto_list->plist[type_select] = '\0';
  2123.       break;
  2124.     }
  2125.       }
  2126.       if (strcmp(proto_list->plist, "FILE") == 0) goto skip_it;
  2127.       strcpy(t_instr, proto_list->plist);
  2128.       strcpy(t_outstr, "FILE");
  2129.       type_select = SUBST_TYPE;
  2130.     } else {
  2131.       /* huh? */
  2132.       fprintf(stderr,
  2133.           "Warning: unable to locate the FILE and varargs replacements\n");
  2134.       hold = TRUE;
  2135.       goto skip_it;
  2136.     }
  2137.  
  2138.     /* copy the information */
  2139.     add_subst(type_select, 2, t_instr, t_outstr);
  2140.  
  2141.   skip_it:
  2142.     /* clean up */
  2143.     pop_proto();
  2144.   }
  2145.  
  2146.   /* get out */
  2147.   return(hold);
  2148. }
  2149.  
  2150. /* read in all configuration files */
  2151. void
  2152. do_config ()
  2153. {
  2154.   /* system configuration file */
  2155.   if (cfg_switch & 1) {
  2156.     parse_config(SYS_CONFIG);
  2157.   }
  2158.  
  2159.   /* personal configuration file */
  2160.   if (cfg_switch & 2) {
  2161.     if (set_home_config()) {
  2162.       parse_config(tmp_str);
  2163.     }
  2164.   }
  2165.  
  2166.   /* current directory */
  2167.   if (cfg_switch & 4) {
  2168.     parse_config(CONFIG_FILE);
  2169.   }
  2170.  
  2171.   /* random config file */
  2172.   if (cfg_file[0] != '\0') {
  2173.     parse_config(cfg_file);
  2174.   }
  2175. }
  2176.  
  2177. /* return pointer to string containing the date */
  2178. char *
  2179. mach_time ()
  2180. {
  2181.   long timeval;
  2182.  
  2183.   timeval = time(0);
  2184.   return(ctime(&timeval));
  2185. }
  2186.  
  2187. #ifdef NO_POPEN
  2188. /* strings for faking a popen call */
  2189. char newcommand[FNAME_SIZE];
  2190. char pipetmpfile[FNAME_SIZE];
  2191. #endif /* NO_POPEN */
  2192.  
  2193. /* function to open a "pipe" to the input */
  2194. FILE *
  2195. open_input (pname, modestr)
  2196.   char *pname, *modestr;
  2197. {
  2198. #ifdef NO_POPEN
  2199.   static int tmpnameset = FALSE;
  2200.  
  2201.   /* build file name */
  2202.   if (tmpnameset == FALSE) {
  2203.     sprintf(pipetmpfile, PIPETMP_FMT, getpid());
  2204.     tmpnameset = TRUE;
  2205.   }
  2206.  
  2207.   /* this "popen()" hack is only useful for reading from the "pipe" */
  2208.   sprintf(newcommand, PIPEOUT_FMT, pname, pipetmpfile);
  2209.   if (system(newcommand) == SYSCMD_FAILED) {
  2210.     return((FILE *) NULL);
  2211.   }
  2212.   return(fopen(pipetmpfile, modestr));
  2213. #else
  2214.   return(popen(pname, modestr));
  2215. #endif /* NO_POPEN */
  2216. }
  2217.  
  2218. /* close up the "pipe" */
  2219. int
  2220. close_input (stream)
  2221.   FILE *stream;
  2222. {
  2223. #ifdef NO_POPEN
  2224.   if (fclose(stream) == EOF) return(-1);
  2225.   return(unlink(pipetmpfile));
  2226. #else
  2227.   return(pclose(stream));
  2228. #endif /* NO_POPEN */
  2229. }
  2230.